package com.autumn.scheduler.job.trigger;

import java.text.ParseException;
import java.util.TimeZone;

import org.quartz.CronExpression;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobDetail;
import org.quartz.ScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;

import com.autumn.scheduler.api.constant.ApiConstants;
import com.autumn.scheduler.api.job.IJobTriggerBuilderInfo;
import com.autumn.scheduler.domain.entities.AutumnJobDetails;
import com.autumn.scheduler.domain.values.SchedulerValue;
import com.autumn.scheduler.job.JobConstants;
import com.autumn.util.ExceptionUtils;
import com.autumn.util.StringUtils;

/**
 * 作业触发器抽象
 *
 * @author 杨昌国 2018-03-20 16:09:20 触发器类型
 */
public abstract class AbstractJobTrigger {

	/**
	 * 北京时区
	 */
	public static final TimeZone BEIJING_TIMEZONE = TimeZone.getTimeZone("GMT+:08:00");

	/**
	 *
	 */
	public AbstractJobTrigger() {

	}

	/**
	 * 创建触发器
	 *
	 * @param jobDetail
	 * @param autumnJobDetail
	 * @param schedulerValue
	 * @return
	 */
	public abstract Trigger createTrigger(JobDetail jobDetail, AutumnJobDetails autumnJobDetail,
			SchedulerValue schedulerValue);

	/**
	 * @param jobDetail
	 * @param autumnJobDetail
	 * @param schedulerValue
	 * @param scheduleBuilder
	 * @return
	 */
	protected final <T extends Trigger> T createTrigger(JobDetail jobDetail, AutumnJobDetails autumnJobDetail,
			SchedulerValue schedulerValue, ScheduleBuilder<T> scheduleBuilder) {
		if (schedulerValue == null) {
			schedulerValue = new SchedulerValue();
		}
		TriggerBuilder<T> triggerBuilder = TriggerBuilder.newTrigger()
				.withIdentity(jobDetail.getKey().getName(), jobDetail.getKey().getGroup()).withSchedule(scheduleBuilder)
				.withDescription(schedulerValue.getTriggerDescription());
		if (schedulerValue.getFirstStartTime() != null) {
			 triggerBuilder = triggerBuilder.startAt(schedulerValue.getFirstStartTime());
		} else {
			triggerBuilder = triggerBuilder.startNow();
		}
		return triggerBuilder.build();
	}

	/**
	 * 创建触发器信息
	 *
	 * @param builderInfo
	 *            生成信息
	 * @return
	 */
	public static AbstractJobTrigger createJobTrigger(IJobTriggerBuilderInfo builderInfo) {
		ExceptionUtils.checkNotNull(builderInfo, "builderInfo");
		if (StringUtils.isNullOrBlank(builderInfo.getTriggerType())) {
			ExceptionUtils.throwValidationException("triggerType 不能为空。");
		}
		if (builderInfo.getTriggerType().equals(ApiConstants.TriggerType.CRON)) {
			if (StringUtils.isNullOrBlank(builderInfo.getCronExpression())) {
				ExceptionUtils.throwValidationException("Cron 表达式不能为空。");
			}
			try {
				CronExpression.validateExpression(builderInfo.getCronExpression().trim());
			} catch (ParseException e) {
				ExceptionUtils.throwValidationException("Cron 表达式不合法。");
			}
			builderInfo.setTimeInterval(null);
			builderInfo.setTimeIntervalUnit("");
			return new CronJobTrigger(builderInfo.getCronExpression().trim());
		} else if (builderInfo.getTriggerType().equals(ApiConstants.TriggerType.SIMPLE)
				|| builderInfo.getTriggerType().equals(ApiConstants.TriggerType.CAL_INT)) {
			if (builderInfo.getTimeInterval() == null || builderInfo.getTimeInterval().intValue() < 1) {
				ExceptionUtils.throwValidationException("时间间隔(timeInterval)不能小于1。");
			}
			if (StringUtils.isNullOrBlank(builderInfo.getTimeIntervalUnit())) {
				ExceptionUtils.throwValidationException("时间间隔单位不能为空。");
			}
			JobConstants.JobIntervalUnitMap.JobIntervalUnitInfo unitInfo = JobConstants.JobIntervalUnitMap
					.getIntervalUnit(builderInfo.getTimeIntervalUnit().trim());
			if (unitInfo == null) {
				throw ExceptionUtils.throwValidationException("时间单位" + builderInfo.getTimeIntervalUnit()
						+ ")不存在或不支持，必须是 " + IntervalUnit.values().toString() + " 之一");
			}
			builderInfo.setCronExpression("");
			if (builderInfo.getTriggerType().equals(ApiConstants.TriggerType.SIMPLE)) {
				return new SimpleJobTrigger(builderInfo.getTimeInterval(), unitInfo.getUnit());
			}
			return new CalendarIntervalJobTrigger(builderInfo.getTimeInterval(), unitInfo.getUnit());
		} else {
			throw ExceptionUtils.throwValidationException("触发器类型(" + builderInfo.getTriggerType() + ") 不受支持。");
		}
	}
}
